package com.colorlight.cloud.gateway.core.message.event.process;

import com.colorlight.cloud.auth.util.TopicUtil;
import com.colorlight.cloud.common.exception.ParameterException;
import com.colorlight.cloud.gateway.core.message.event.manager.ProcessMessageEventHandlerManager;
import com.colorlight.cloud.gateway.api.message.constraint.protocol.ProtocolType;
import com.colorlight.cloud.gateway.api.message.constraint.schedule.ScheduleActions;
import com.colorlight.cloud.gateway.api.message.convert.MessageTransition;
import com.colorlight.cloud.gateway.api.message.model.Msg;
import com.colorlight.cloud.gateway.api.message.process.ProcessMessageEventHandler;
import com.colorlight.cloud.mqtt.base.api.message.ProcessMessage;
import com.colorlight.cloud.mqtt.base.entity.SubMessage;
import com.iot.proto.gateway.Gateway;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Objects;

import static com.colorlight.cloud.common.constants.CommonConstants.DEVICE_NAME;
import static com.colorlight.cloud.common.constants.CommonConstants.PRODUCT_KEY;
import static com.colorlight.cloud.gateway.core.model.GatewayCoreExceptionEnum.SCHEDULE_ACTIONS_INVALID_PARAMETER_EXCEPTION;

/**
 * @author Demon
 * @date 15/1/2024  下午4:51
 */
@Component
@Slf4j
public class ProcessMessageGatewayImpl implements ProcessMessage {
	private final ProcessMessageEventHandlerManager processMessageEventHandlerManager;
	
	private final MessageTransition messageTransition;
	
	public ProcessMessageGatewayImpl(ProcessMessageEventHandlerManager processMessageEventHandlerManager, MessageTransition messageTransition) {
		this.processMessageEventHandlerManager = processMessageEventHandlerManager;
		
		this.messageTransition = messageTransition;
	}
	
	
	@Override
	public void process(SubMessage<byte[]> subMessage) {
		String topic = subMessage.getTopic();
		Map<String, String> map = TopicUtil.getTopicInfo(topic);
		final String deviceName = map.get(DEVICE_NAME);
		final String protocolName = map.get(PRODUCT_KEY);
		//先解析消息
		Gateway.Msg sources = messageTransition.bytesTransFormMessageLite(subMessage.getMessage());
		final String instructionName =sources.getNameStruct().name();
		//主题解析
		String temp = protocolName;
		//fixme
		if(!"Xm".equalsIgnoreCase(protocolName)&&!"GrandShow".equalsIgnoreCase(protocolName)){
			temp = "Complete";
		}
		ProcessMessageEventHandler<?> handler = processMessageEventHandlerManager.getHandler(temp, instructionName);
		if (Objects.isNull(handler)) {
			log.warn("未处理上报\n 上报主题:{} \n消息详情:{}", subMessage.getTopic(), subMessage.getMessage());
			return;
		}

		
		Enum<? extends ProtocolType> instructionType = handler.getInstructionType();
		ProtocolType protocolType = (ProtocolType) instructionType;
		Class<? extends ScheduleActions> scheduleClass = protocolType.getScheduleClass();
		//通过反射 构建对象
		ScheduleActions target = builderNilScheduleActions(scheduleClass);
		Msg msg = messageTransition.toMsg(sources, target);
		log.info("设备名称：{}\n协议类型：{}\n上报信息：{}", deviceName, protocolName, msg);
		//消息上报
		handler.accept(deviceName, protocolName, msg);
		//消息处理
	}
	
	/**
	 * 通过反射创建实体对象
	 *
	 * @param scheduleClass 指令类型
	 * @return 目标对象
	 * @author Demon
	 * @date 29/12/2023/上午11:18
	 */
	private ScheduleActions builderNilScheduleActions(Class<? extends ScheduleActions> scheduleClass) {
		// 通过反射创建对象
		ScheduleActions scheduleActions = null;
		try {
			Constructor<? extends ScheduleActions> declaredConstructor = scheduleClass.getDeclaredConstructor();
			// 构造方法公有化
			declaredConstructor.setAccessible(true);
			scheduleActions = declaredConstructor.newInstance();
			
		} catch (InstantiationException
				| IllegalAccessException
				| InvocationTargetException
				| NoSuchMethodException instantiationException) {
			instantiationException.printStackTrace();
		}
		if (Objects.isNull(scheduleActions)) {
			throw new ParameterException(SCHEDULE_ACTIONS_INVALID_PARAMETER_EXCEPTION);
		}
		return scheduleActions;
	}
}
